package com.yanqu.road.server.manager.activity.twins.activity;

import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.twins.*;
import com.yanqu.road.entity.activity.twins.config.TwinsConfig;
import com.yanqu.road.entity.activity.twins.config.TwinsLotteryConfig;
import com.yanqu.road.entity.activity.twins.config.TwinsPvpConfig;
import com.yanqu.road.entity.enums.eChatContentType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eMessageType;
import com.yanqu.road.entity.player.CrossUserBaseInfo;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.bussiness.activity.TwinsBusiness;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.TwinsProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityChatMgr;
import com.yanqu.road.server.manager.log.CrossActivityLogMgr;
import com.yanqu.road.server.manager.player.WorldMessageMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class CrossTwinsActivity {

    private Logger logger = LogManager.getLogger(CrossTwinsActivity.class.getName());

    private Map<Long,Object> lockMap = new ConcurrentHashMap<>();

    private TwinsConfig config;

    private int groupId;

    private RandomHelper randomHelper = new RandomHelper();

    //boss编号
    private AtomicInteger bossNo = new AtomicInteger(1);

    //user编号
    private AtomicInteger userNo = new AtomicInteger(1);

    private CrossTwinsLuckDrawData drawData;

    private Map<Integer,CrossTwinsBossData> bossDataMap = new ConcurrentHashMap<>();

    //用户数据，用户id
    private Map<Long, CrossTwinsUserData> userDataMap = new ConcurrentHashMap<>();

    //被打用户数据归类 数据库初始化的时候初始化一下
    private Map<Long, Map<Long,CrossTwinsUserData>> beAttackUserMap = new ConcurrentHashMap<>();

    //打别人的人
    private Map<Long,CrossTwinsUserData> attackUserMap = new ConcurrentHashMap<>();

    //无所事事的人
    private Map<Long,CrossTwinsUserData> wanderUserMap = new ConcurrentHashMap<>();

    private Map<Integer,List<Long>> enterBossRoomMap = new ConcurrentHashMap<>();

    //-------------------------------------------------保存数据------------------------------------------------------
    private List<CrossTwinsBossData> needInsertBossData = new ArrayList<>();
    private List<CrossTwinsBossData> needUpdateBossData = new ArrayList<>();

    private List<CrossTwinsUserData> needInsertUserData = new ArrayList<>();
    private List<CrossTwinsUserData> needUpdateUserData = new ArrayList<>();

    private List<CrossTwinsDamageRecordData> needInsertDamageRecordData = new ArrayList<>();
    private List<CrossTwinsDamageRecordData> needUpdateDamageRecordData = new ArrayList<>();

    //-------------------------------------------------同步数据------------------------------------------------------
    //需要同步的声望
    private List<CrossTwinsUserData> needSyncPopList = new ArrayList<>();

    //抽奖记录
    private List<CrossTwinsLuckDrawRecordData> recordList = new ArrayList<>();

    private List<CrossTwinsLuckDrawRecordData> needSyncRecordList = new ArrayList<>();


    public CrossTwinsActivity(ActivityInfo activityInfo,int groupId) {
        Map<String, ActivityConfig> activityConfigMap = ActivityBussiness.getActivityConfigMap(Collections.singletonList(activityInfo.getActivityId())).get(activityInfo.getActivityId());
        Map<Integer, TwinsPvpConfig> tempPvpConfigMap = TwinsBusiness.getPvpConfigMap(activityInfo.getActivityId());
        Map<Integer, TwinsLotteryConfig> tempLotteryConfigMap = TwinsBusiness.getLotteryConfigMap(activityInfo.getActivityId());

        TwinsConfig tempConfig = new TwinsConfig();
        tempConfig.setActivityInfo(activityInfo);
        tempConfig.initCrossConfig(activityConfigMap,tempPvpConfigMap,tempLotteryConfigMap);

        config = tempConfig;

        this.groupId = groupId;

        bossNo = new AtomicInteger(TwinsBusiness.getMaxBossNo(getActivityId(),groupId));
        userNo = new AtomicInteger(TwinsBusiness.getMaxUserNo(getActivityId(),groupId));
        bossDataMap = TwinsBusiness.getBossDataList(getActivityId(),groupId);
        userDataMap = TwinsBusiness.getUserDataList(getActivityId(),groupId);
        initBossDataAndUserData();

        drawData = TwinsBusiness.getCrossTwinsDrawData(getActivityId(),groupId);
        if(drawData == null){
            drawData = new CrossTwinsLuckDrawData();
            drawData.setActivityId(getActivityId());
            drawData.setGroupId(groupId);
            drawData.setInsertOption();
        }

    }

    //把玩家分类一下到对应的缓存，把记录分配一下到对应的玩家身上
    private void initBossDataAndUserData(){
        List<Integer> bossNoList = new ArrayList<>();
        for(CrossTwinsBossData bossData : bossDataMap.values()){
            bossNoList.add(bossData.getBossNo());
            if(!bossDamageMap.containsKey(bossData.getBossId())){
                bossDamageMap.put(bossData.getBossId(),new ArrayList<>());
            }
        }
        for(CrossTwinsUserData userData : userDataMap.values()){
            if(bossDataMap.containsKey(userData.getBossId())){
                bossDataMap.get(userData.getBossId()).getUserDataMap().put(userData.getUserId(),userData);
            }
            if(!beAttackUserMap.containsKey(userData.getUserId())){
                beAttackUserMap.put(userData.getUserId(),new ConcurrentHashMap<>());
            }
            if(!userDamageMap.containsKey(userData.getUserId())){
                userDamageMap.put(userData.getUserId(),new ArrayList<>());
            }
            changeUserPlace(userData,0);
        }

        List<CrossTwinsDamageRecordData> recordList = TwinsBusiness.getDamageRecordDataList(getActivityId(),groupId,bossNoList);
        for(CrossTwinsDamageRecordData recordData : recordList){
            if(recordData.getAttackUserId() == 0){
                continue;
            }
            if(recordData.getAttackUserId() != 0){
                CrossTwinsUserData userData = getUserData(recordData.getUserId());
                if(userData != null){
                    if(!userData.getAttackDamageRecordMap().containsKey(recordData.getAttackUserNo())){
                        userData.getAttackDamageRecordMap().put(recordData.getAttackUserNo(),new ConcurrentHashMap<>());
                    }
                    userData.getAttackDamageRecordMap().get(recordData.getAttackUserNo()).put(recordData.getUserNo(),recordData);
                }
                CrossTwinsUserData beAttackUserData = getUserData(recordData.getAttackUserId());
                if(beAttackUserData != null){
                    if(!beAttackUserData.getBeAttackDamageRecordMap().containsKey(recordData.getAttackUserNo())){
                        beAttackUserData.getBeAttackDamageRecordMap().put(recordData.getAttackUserNo(),new ConcurrentHashMap<>());
                    }
                    beAttackUserData.getBeAttackDamageRecordMap().get(recordData.getAttackUserNo()).put(recordData.getUserNo(),recordData);
                }
            }
        }
    }

    private void addNeedSyncCondition(CrossTwinsUserData data){
        synchronized (needSyncPopList){
            if(!needSyncPopList.contains(data)){
                needSyncPopList.add(data);
            }
        }
    }

    private void addNeedInsertBossData(CrossTwinsBossData data){
        synchronized (needInsertBossData){
            if(!needInsertBossData.contains(data)){
                needInsertBossData.add(data);
            }
        }
    }

    private void addNeedUpdateBossData(CrossTwinsBossData data){
        synchronized (needUpdateBossData){
            if(!needUpdateBossData.contains(data)){
                needUpdateBossData.add(data);
            }
        }
    }


    private void addNeedInsertUserData(CrossTwinsUserData data){
        synchronized (needInsertUserData){
            if(!needInsertUserData.contains(data)){
                needInsertUserData.add(data);
            }
        }
    }

    private void addNeedUpdateUserData(CrossTwinsUserData data){
        synchronized (needUpdateUserData){
            if(!needUpdateUserData.contains(data)){
                needUpdateUserData.add(data);
            }
        }
    }


    private void addNeedInsertDamageRecordData(CrossTwinsDamageRecordData data){
        synchronized (needInsertUserData){
            if(!needInsertDamageRecordData.contains(data)){
                needInsertDamageRecordData.add(data);
            }
        }
    }

    private void addNeedUpdateDamageRecordData(CrossTwinsDamageRecordData data){
        synchronized (needUpdateUserData){
            if(!needUpdateDamageRecordData.contains(data)){
                needUpdateDamageRecordData.add(data);
            }
        }
    }


    private void removeUserFromBossRoom(List<Long> userIdList){
        List<Long> removeUserIdList = new ArrayList<>();
        List<Long> debugUserIdList = new ArrayList<>(debugUserMap.keySet());
        for(long userId : userIdList){
            if(!debugUserIdList.contains(userId)){
                removeUserIdList.add(userId);
            }
        }
        for(int bossId : enterBossRoomMap.keySet()){
            List<Long> ruserIdList = enterBossRoomMap.get(bossId);
            synchronized (ruserIdList){
                ruserIdList.removeAll(removeUserIdList);
            }
        }
    }

    private synchronized Object getUserLock(long userId){
        if(!lockMap.containsKey(userId)){
            lockMap.put(userId,new Object());
        }
        return lockMap.get(userId);
    }




    public ActivityInfo getActivity(){
        return config.getActivityInfo();
    }

    public int getActivityId(){
        if(config != null && config.getActivityInfo() != null){
            return config.getActivityInfo().getActivityId();
        }
        return 0;
    }

    //五秒钟同步一次的
    private long last5SecTime = 0;

    //1秒同步一次的
    private long last1SecTime = 0;

    //数据库初始化的时候初始化一下 攻击玩家的同步
    private Map<Long,List<CrossTwinsBeatDamageData>> userDamageMap = new ConcurrentHashMap<>();
    //数据库初始化的时候初始化一下 攻击boss的同步
    private Map<Integer,List<CrossTwinsBeatDamageData>> bossDamageMap = new ConcurrentHashMap<>();

    public void slowLogic(){
        long nowTime = System.currentTimeMillis();
        checkRoomUser();
        if(nowTime - last5SecTime > 5 * DateHelper.SECOND_MILLIONS){
            tempCheck();
            last5SecTime = nowTime;
            syncUserNearBySlow();
//            syncBoosBoolSlow();
            syncDrawRewardList();
        }
        syncPopList();
        hpReset();
    }

    private void hpReset(){
        for(CrossTwinsUserData userData : userDataMap.values()){
            synchronized (getUserLock(userData.getUserId())){
                //玩家用了体力道具最大值了就不变了吧
                if(userData.getHpTime() != DateHelper.getTodayZeroTimeStamp() && userData.getHp() < config.getPvpHpMax()){
                    userData.setHp(config.getPvpHpMax());
                    userData.setHpTime(DateHelper.getTodayZeroTimeStamp());
                }
            }
        }
    }

    private void timeOver(){
        if(!isPvpTime()){
            for(CrossTwinsBossData bossData : bossDataMap.values()){
                if(bossData.getBool().compareTo(BigInteger.ZERO) > 0){
                    bossDie(bossData,null);
                }
            }
        }
    }

    public void fastLogic(){
        long nowTime = System.currentTimeMillis();
        checkBoss(nowTime);
        timerBeatLogic();
        timeOver();

        if(nowTime - last1SecTime > DateHelper.SECOND_MILLIONS){
            last1SecTime = nowTime;
            syncSelfBool();
//            syncUserNearBy();
            syncBoosBool();
        }
    }


    //同步自己周围的人的信息
    private void syncUserNearBySlow(){
        for(int bossId : enterBossRoomMap.keySet()){
            syncUserNearBy(bossId,new ArrayList<>(enterBossRoomMap.get(bossId)));
        }
    }

    private void syncUserNearBy(int bossId,List<Long> userIdList){
        for(long userId : userIdList){
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            if(userBaseInfo == null)continue;
            TwinsProto.TwinsPvpSyncUserMsg.Builder syncMsg = TwinsProto.TwinsPvpSyncUserMsg.newBuilder();
            List<CrossTwinsUserData> nearbyUserList = getNearByUser(bossId,userId);
            for(CrossTwinsUserData userData : nearbyUserList){
                TwinsProto.TwinsPvpUserMsg.Builder userMsg = parseTwinsPvpUserMsg(userData);
                if(userMsg != null){
                    syncMsg.addUser(userMsg);
                }
            }
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_SYNC_USER, syncMsg);
            MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, pbMsg);
        }
    }

    //同步自己的血量
    private void syncSelfBool(){
        Map<Long,List<CrossTwinsBeatDamageData>> tempMap = new ConcurrentHashMap<>();
        for(long userId : userDamageMap.keySet()){
            List<CrossTwinsBeatDamageData> daList = userDamageMap.get(userId);
            if(daList.size() > 0){
                synchronized (daList){
                    tempMap.put(userId,new ArrayList<>(daList));
                    daList.clear();
                }
            }
        }
        for(long userId : tempMap.keySet()){
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            if(userBaseInfo == null)continue;
            TwinsProto.TwinsPvpSyncSelfMsg.Builder syncMsg = TwinsProto.TwinsPvpSyncSelfMsg.newBuilder();
            BigInteger minBool = BigInteger.valueOf(Integer.MAX_VALUE);
            for(CrossTwinsBeatDamageData data : tempMap.get(userId)){
                TwinsProto.TwinsPvpBeatMsg.Builder beatMsg = TwinsProto.TwinsPvpBeatMsg.newBuilder();
                if(data.getUserBool().compareTo(minBool) < 0){
                    minBool = data.getUserBool();
                }
                beatMsg.setUserId(data.getAttackUserId());
                beatMsg.setBool(data.getDamage().toString());
                syncMsg.addBeat(beatMsg);
                if(data.getUserBool().equals(BigInteger.ZERO) && data.getAttackUserId() != 0){
                    CrossTwinsUserData twinsUserData = getUserData(data.getAttackUserId());
                    TwinsProto.TwinsPvpUserMsg.Builder userMsg = parseTwinsPvpUserMsg(twinsUserData);
                    syncMsg.setPlayerData(userMsg);
                }
            }
            syncMsg.setBool(minBool.toString());

            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_SYNC_SELF, syncMsg);
            MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, pbMsg);
        }
    }

    private void syncBoosBool(){
        for(int bossId : enterBossRoomMap.keySet()){
            List<CrossTwinsBeatDamageData> damageList = bossDamageMap.get(bossId);
            if(damageList.size() > 0){
                synchronized (damageList){
                    List<Long> userList = new ArrayList<>(enterBossRoomMap.get(bossId));
                    userList.removeAll(debugUserMap.keySet());
                    CrossTwinsBossData bossData = getBossData(bossId);
                    for(long userId : userList){
                        syncBossBool(userId,bossData,damageList);
                    }
                    damageList.clear();
                }

            }
        }
    }

    private void syncBossBool(long userId , CrossTwinsBossData bossData,List<CrossTwinsBeatDamageData> damageList){
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if(userBaseInfo == null)return;
        TwinsProto.TwinsPvpSyncBossMsg.Builder syncBossMsg = TwinsProto.TwinsPvpSyncBossMsg.newBuilder();
        syncBossMsg.setBossId(bossData.getBossId());
        syncBossMsg.setBool(bossData.getBool().toString());
        for(CrossTwinsBeatDamageData damageData : damageList){
            TwinsProto.TwinsPvpBeatBossMsg.Builder beatMsg = TwinsProto.TwinsPvpBeatBossMsg.newBuilder();
            beatMsg.setUserId(damageData.getUserId());
            beatMsg.setAttackValue(damageData.getDamage().toString());
            syncBossMsg.addBeats(beatMsg);
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_SYNC_BOSS, syncBossMsg);
        MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, pbMsg);
    }

    //todo-xx 去掉校验，数据有问题自己修复
    private void tempCheck(){
        Map<Integer,Integer> bossUserCountMap = new ConcurrentHashMap<>();
        for(CrossTwinsUserData userData : userDataMap.values()){
            if(userData.getAttackUserId() != 0){
                CrossTwinsUserData beAttUser = userDataMap.get(userData.getAttackUserId());
                if(beAttUser.getBossId() == 0 || beAttUser.getRoomBool().equals(BigInteger.ZERO)){
                    logger.error("异常");
                }
            }
            if(userData.getBossId() != 0){
                bossUserCountMap.put(userData.getBossId(),bossUserCountMap.getOrDefault(userData.getBossId(),0) + 1);
            }
        }
        for(CrossTwinsBossData bossData : bossDataMap.values()){
            if(bossData.getUserDataMap().size() != bossUserCountMap.getOrDefault(bossData.getBossId(),0)){
                logger.error("异常");
            }
            for(CrossTwinsUserData userData : bossData.getUserDataMap().values()){
                if(userData.getBossId() != bossData.getBossId() || userData.getBossId() == 0){
                    bossData.getUserDataMap().remove(userData.getUserId());
                    logger.error("异常");
                }
            }
        }
    }

    private void timerBeatLogic(){
        long nowTime = System.currentTimeMillis();
        List<CrossTwinsUserData> userDataList = new ArrayList<>(debugUserMap.values());
        userDataList.sort(new AttackIndexSort());
        for(CrossTwinsUserData userData : userDataList){
            if(userData.getStatus() == 0)continue;
            if(nowTime - userData.getLastAttackTime() < config.getPvpAttackCd()){
                continue;
            }
            BigInteger attackValue = BigInteger.ZERO;
            if(userData.getStatus() == 2 && userData.getAttackUserId() != 0){
                synchronized (getUserLock(userData.getAttackUserId())){
                    attackValue = beatUser(userData);
                    if(attackValue.compareTo(BigInteger.ZERO) > 0){
                        userData.setLastAttackTime(System.currentTimeMillis());
                    }
                }
            }else if(userData.getStatus() == 1){
                CrossTwinsBossData bossData = getBossData(userData.getBossId());
                synchronized (bossData){
                    attackValue = beatBoss(userData);
                    if(attackValue.compareTo(BigInteger.ZERO) > 0){
                        userData.setLastAttackTime(System.currentTimeMillis());
                    }
                }
            }
        }
    }

    //获取玩家血量，客户端打玩家打了自己请求
    public void getUserBool(long serverId, long userId, TwinsProto.TwinsPvpGetUserInfoReqMsg reqMsg) {
        TwinsProto.TwinsPvpGetUserInfoRespMsg.Builder respMsg = TwinsProto.TwinsPvpGetUserInfoRespMsg.newBuilder();
        respMsg.setRet(0);
        CrossTwinsUserData userData = getUserData(userId);
        if(userData.getBossId() == 0){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_ENTER_BOSS_ROOM);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_USER_BOOL, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        long searchUserId = 0;
        CrossTwinsBossData bossData = getBossData(userData.getBossId());
        for(long bossUserId : bossData.getUserDataMap().keySet()){
            UserBaseInfo searchUserBaseInfo = CrossUserMgr.getUserBaseInfo(bossUserId);
            if(searchUserBaseInfo != null && searchUserBaseInfo.getUserAliasId() == reqMsg.getAliUserId()){
                searchUserId = bossUserId;
            }
        }
        if(searchUserId == 0){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_SEARCH_USER);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_USER_BOOL, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(searchUserId);
        if(userBaseInfo == null){
            respMsg.setRet(GameErrorCode.E_TWINS_PARAMS);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_USER_BOOL, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        CrossTwinsUserData searchUserData = getUserData(searchUserId);
        if(searchUserData == null){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_USER_DATA_NOT_EXIT);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_USER_BOOL, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        TwinsProto.TwinsPvpUserSearchMsg.Builder userMsg = parseTwinsPvpUserSearchMsg(userData.getUserNo(),searchUserData);
        if(userMsg != null){
            respMsg.setUser(userMsg);
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_USER_BOOL, respMsg);
        MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, pbMsg);
    }

    private TwinsProto.TwinsPvpUserSearchMsg.Builder parseTwinsPvpUserSearchMsg(int userNo,CrossTwinsUserData userData){
        if(userData == null){
            return null;
        }
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
        if(userBaseInfo == null){
            return null;
        }
        TwinsProto.TwinsPvpUserSearchMsg.Builder userMsg = TwinsProto.TwinsPvpUserSearchMsg.newBuilder();
        userMsg.setUserId(userData.getUserId());
        PlayerProto.PlayerBaseTempMsg.Builder baseMsg = PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo);
        userMsg.setPlayerBaseData(baseMsg);
        userMsg.setMaxBool(userData.getRoomMaxBool().toString());
        userMsg.setBool(userData.getRoomBool().toString());
        userMsg.setAttack(userData.getRoomAttack().toString());
        userMsg.setBossId(userData.getBossId());
        userMsg.setAttackUserId(userData.getAttackUserId());
        userMsg.setAttackScore((int)userData.getAttackScore());
        userMsg.setAttackTime(userData.getAttackTime());
        userMsg.setAttackValue("0");
        CrossTwinsBossData bossData = getBossData(userData.getBossId());
        //我这条命对别人造成了多少伤害
        if(bossData != null && userData.getAttackDamageRecordMap().containsKey(userNo)){
            Map<Integer, CrossTwinsDamageRecordData> attackUserMap = userData.getAttackDamageRecordMap().get(userNo);
            if(attackUserMap.containsKey(userData.getUserNo())){
                userMsg.setAttackValue(attackUserMap.get(userData.getUserNo()).getDamage().toString());
            }
        }

        return userMsg;
    }

    //记录抽奖了第几次了以及抽奖中了什么东西
    private void addUserDrawItem(long userId,int drawItemId){
        drawData.setDrawTimes(drawData.getDrawTimes() + 1);
        CrossTwinsUserData userData = getUserData(userId);
        userData.setDrawTimes(userData.getDrawTimes() + 1);
        TwinsLotteryConfig hideConfig = config.getHideLotteryConfig();
        //累计没中大奖的保底,保底要在抽了drawTimesM次之后才开始计时
        int drawTimes = userData.getDrawTimes();
        int drawTimesN = config.getLuckDrawParamList().get(0);
        int drawTimesM = config.getLuckDrawAddParamList().get(0);
        if(drawTimesM <= drawTimesN){
            drawTimesM = drawTimesN + 1;
        }
        if(drawItemId != hideConfig.getRewards() && drawTimes > drawTimesM){
            userData.setDrawNoBigCount(userData.getDrawNoBigCount() + 1);
        }else{
            userData.setDrawNoBigCount(0);
        }

        if(!userData.getDrawItemList().contains(drawItemId)){
            userData.getDrawItemList().add(drawItemId);
        }
        userData.setLastDrawItemId(drawItemId);
        addNeedUpdateUserData(userData);
        addLuckDrawRecord(userId,drawItemId);
    }

    private void addLuckDrawRecord(long userId,int rewardItemId){
        CrossTwinsLuckDrawRecordData recordData = new CrossTwinsLuckDrawRecordData();
        recordData.setActivityId(getActivityId());
        recordData.setUserId(userId);
        recordData.setRewardItemId(rewardItemId);
        recordData.setTime(System.currentTimeMillis());
        synchronized (recordList){
            recordList.add(recordData);
            if(recordList.size() > config.getLuckDrawRecordCount()){
                recordList.remove(0);
            }
            needSyncRecordList.add(recordData);
        }
    }

    //算保底规则和隐藏款规则的抽奖次数大于M
    private int luckDrawRandom(long userId){
        CrossTwinsUserData userData = getUserData(userId);
        int drawTimesN = config.getLuckDrawParamList().get(0);
        int drawTimesM = config.getLuckDrawAddParamList().get(0);
        if(drawTimesM <= drawTimesN){
            drawTimesM = drawTimesN + 1;
        }
        int drawLuckAdd = config.getLuckDrawAddParamList().get(1);
        int drawTimes = userData.getDrawTimes();
        int noBigDrawCount = userData.getDrawNoBigCount();
        int luckValueAdd = 0;
        if(drawTimes > drawTimesM){
            luckValueAdd = noBigDrawCount * drawLuckAdd;
        }
        int drawNum = userData.getDrawTimes();
        List<Integer> luckDrawMustItemCountList = config.getLuckDrawMustItemCountList();
        List<Integer> luckDrawMustDrawCountList = config.getLuckDrawMustDrawCountList();
        //不会抽中的东西
        List<Integer> itemList = new ArrayList<>();
        //上次抽中的不会再抽中
        if(userData.getLastDrawItemId() != 0){
            itemList.add(userData.getLastDrawItemId());
        }
        //到达了必中没抽中的次数把抽中的放进来
        if(luckDrawMustDrawCountList.contains(drawNum + 1)){
            int itemCount = luckDrawMustItemCountList.get(luckDrawMustDrawCountList.indexOf(drawNum + 1));
            List<Integer> drawItemList = userData.getDrawItemList();
            if(drawItemList.size() < itemCount){
                itemList = new ArrayList<>(drawItemList);
            }
        }
        Map<Integer, TwinsLotteryConfig> lotteryConfigMap = config.getLotteryConfigMap();
        Map<Integer, Integer> itemWeightMap = new ConcurrentHashMap<>();
        for(TwinsLotteryConfig lotteryConfig : lotteryConfigMap.values()){
            //不在的就是没抽中的，没有必中的话itemList也是空的，所有加进来
            if(!itemList.contains(lotteryConfig.getRewards())){
                if(lotteryConfig.getWeights() == 0)continue;
                if(lotteryConfig.getIsHide() == 1){
                    itemWeightMap.put(lotteryConfig.getRewards(),lotteryConfig.getWeights() + luckValueAdd);
                }else{
                    itemWeightMap.put(lotteryConfig.getRewards(),lotteryConfig.getWeights());
                }
            }
        }
        int rewardItemId = 0;
        int totalWeight = 0;
        if(itemWeightMap.size() == 0){
            logger.info("绝代双骄{}抽皮肤配错错误,第{}次抽奖不可能达到{}个不一样",getActivityId(),drawNum+1,luckDrawMustItemCountList.get(luckDrawMustDrawCountList.indexOf(drawNum + 1)));
            //直接全部随机了，补奖励不得蛋疼死
            for(TwinsLotteryConfig lotteryConfig : lotteryConfigMap.values()){
                if(lotteryConfig.getWeights() == 0)continue;
                if(lotteryConfig.getIsHide() == 1){
                    itemWeightMap.put(lotteryConfig.getRewards(),lotteryConfig.getWeights() + luckValueAdd);
                }else{
                    itemWeightMap.put(lotteryConfig.getRewards(),lotteryConfig.getWeights());
                }
            }
        }
        for (int itemId : itemWeightMap.keySet()) {
            int weight = itemWeightMap.get(itemId);
            totalWeight += weight;
        }
        int randomNum = randomHelper.next(0, totalWeight);
        for (int itemId : itemWeightMap.keySet()) {
            int value = itemWeightMap.get(itemId);
            if (randomNum < value) {
                rewardItemId = itemId;
                break;
            }
            randomNum -= value;
        }
        synchronized (drawData){
            addUserDrawItem(userId,rewardItemId);
        }
        return rewardItemId;
    }

    //抽一次奖 //算保底规则和隐藏款规则的抽奖次数小于n
    private int luckDrawOne(long userId){
        CrossTwinsUserData userData = getUserData(userId);
        //小于这个值有个奖池大家一起有一个概率中奖
        int drawTimesN = config.getLuckDrawParamList().get(0);
        int luckCount = config.getLuckDrawParamList().get(1) * getActivity().getServerIdList().size();
        int luckValue = config.getLuckDrawParamList().get(2);//抽检概率
        TwinsLotteryConfig hideConfig = config.getHideLotteryConfig();
        if(drawData.getDrawTimes() < drawTimesN && drawData.getLuckCount() < luckCount && hideConfig.getRewards() != userData.getLastDrawItemId()){
            synchronized (drawData){
                if(drawData.getDrawTimes() < drawTimesN && drawData.getLuckCount() < luckCount){
                    int luckDrawValue = randomHelper.next(0,1000);
                    //中奖了
                    if(luckDrawValue < luckValue){
                        drawData.setLuckCount(drawData.getLuckCount() + 1);
                        addUserDrawItem(userId,hideConfig.getRewards());
                        return hideConfig.getRewards();
                    }
                }
            }
        }
        return luckDrawRandom(userId);
    }

    //幸运抽奖
    public void luckDraw(long serverId, long userId, TwinsProto.TwinsLuckDrawReqMsg reqMsg) {
        TwinsProto.TwinsLuckDrawRespMsg.Builder respMsg = TwinsProto.TwinsLuckDrawRespMsg.newBuilder();
        respMsg.setRet(0);
        int times = reqMsg.getTimes();
        respMsg.setTimes(times);
        Property reward = new Property();
        for(int i = 0; i< times; i++){
            int rewardItemId = luckDrawOne(userId);
            if(rewardItemId != 0){
                reward.addProperty(PropertyHelper.parseStringToProperty(rewardItemId + "=1"));
            }
        }

        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_TWINS_CROSS_LUCK_DRAW, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    public void luckDrawRecord(long serverId, long userId, TwinsProto.TwinsLuckDrawRecordReqMsg reqMsg) {
        TwinsProto.TwinsLuckDrawRecordSyncMsg.Builder respMsg = TwinsProto.TwinsLuckDrawRecordSyncMsg.newBuilder();
        List<CrossTwinsLuckDrawRecordData> tempRecordList = new ArrayList<>(recordList);

        int recordCount = config.getLuckDrawRecordCount();
        if(tempRecordList.size() < recordCount){
            recordCount = tempRecordList.size();
        }
        for(int i = recordCount - 1;i >= 0;i--){
            CrossTwinsLuckDrawRecordData recordData = tempRecordList.get(i);
            respMsg.addInfo(parseTwinsLuckDrawRecordTempMsg(recordData));
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_LUCK_DRAW_RECORD, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    private TwinsProto.TwinsLuckDrawRecordTempMsg.Builder parseTwinsLuckDrawRecordTempMsg(CrossTwinsLuckDrawRecordData recordData){
        TwinsProto.TwinsLuckDrawRecordTempMsg.Builder respMsg = TwinsProto.TwinsLuckDrawRecordTempMsg.newBuilder();
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(recordData.getUserId());
        respMsg.setUserId(recordData.getUserId());
        respMsg.setServerId(0);
        respMsg.setNickName("");
        if(userBaseInfo != null){
            respMsg.setServerId(userBaseInfo.getServerId());
            respMsg.setNickName(userBaseInfo.getNickName());
        }
        respMsg.setReward(recordData.getRewardItemId() + "=1");
        respMsg.setTime(recordData.getTime());
        return respMsg;
    }

    //加体力
    public void addHp(long serverId, long userId, TwinsProto.CrossTwinsPvpHpAddReqMsg reqMsg) {
        CrossTwinsUserData userData = getUserData(userId);
        if(userData != null){
            userData.setHp(userData.getHp() + reqMsg.getAddValue());
        }
        pvpSyncUserData(serverId,userId);
    }

    private Map<Long,CrossTwinsUserData> debugUserMap = new ConcurrentHashMap<>();
    //pvp调试
    public void pvpDebug(long serverId, long userId, TwinsProto.CrossTwinsPvpDebugUserReqMsg reqMsg) {
        int attBoosCount = reqMsg.getAttBossCount();
        long attUserId = reqMsg.getAttUserId();
        int attUserCount = reqMsg.getAttUserCount();
        int attBossId = reqMsg.getBossId();
        for(TwinsProto.CrossTwinsPvpUpdateUserMsg userMsg : reqMsg.getUserList()){
            if(userMsg.getPlayerBaseData() != null){
                UserBaseInfo userBaseInfo = PlayerBasePb.parseToUserBaseInfo(userMsg.getPlayerBaseData());
                CrossUserMgr.updateUserBaseInfoChange(userMsg.getUserId(),userBaseInfo);
            }
            CrossTwinsUserData userData = initUserData(userMsg.getUserId(),new BigInteger(userMsg.getBool()),new BigInteger(userMsg.getAttack()));
            synchronized (debugUserMap){
                if(!debugUserMap.containsKey(userData.getUserId())){
                    debugUserMap.put(userData.getUserId(),userData);
                }
            }
        }
        Map<Integer,Integer> bossEnterCountMap = new ConcurrentHashMap<>();
        for(CrossTwinsUserData userData : debugUserMap.values()){
            int bossId = pvpDebugEnterBossRoom(userData,attBossId);
            bossEnterCountMap.put(bossId,bossEnterCountMap.getOrDefault(bossId,0) + 1);
        }
        for(int bossId : bossEnterCountMap.keySet()){
            logger.info("绝代{}boss{}房间进入{}个模拟玩家",getActivityId(),bossId,bossEnterCountMap.get(bossId));
        }
        Map<Integer,Integer> bossAttCountMap = new ConcurrentHashMap<>();
        Map<Integer,Integer> userAttCountMap = new ConcurrentHashMap<>();
        for(CrossTwinsUserData userData : debugUserMap.values()){
            if(bossAttCountMap.getOrDefault(userData.getBossId(),0) < attBoosCount){
                pvpDebugBeat(userData,-1);
                bossAttCountMap.put(userData.getBossId(),bossAttCountMap.getOrDefault(userData.getBossId(),0) + 1);
            }else if(userAttCountMap.getOrDefault(userData.getBossId(),0) < attUserCount){
                pvpDebugBeat(userData,attUserId);
                userAttCountMap.put(userData.getBossId(),userAttCountMap.getOrDefault(userData.getBossId(),0) + 1);
            }else{
                if(attUserId == 1){
                    pvpDebugBeat(userData,1);
                }else{
                    pvpDebugBeat(userData,0);
                }
            }
        }
        for(int bossId : bossAttCountMap.keySet()){
            logger.info("绝代{}boss{}房间{}个玩家攻击boss",getActivityId(),bossId,bossAttCountMap.get(bossId));
        }
        for(int bossId : userAttCountMap.keySet()){
            logger.info("绝代{}boss{}房间{}个玩家攻击玩家{}",getActivityId(),bossId,userAttCountMap.get(bossId),attUserId);
        }
    }

    private int pvpDebugEnterBossRoom(CrossTwinsUserData userData,int attBossId){
        if(userData.getBossId() != 0){
            return 0;
        }
        List<Integer> goBossIdList = new ArrayList<>();
        Map<Integer,CrossTwinsBossData> bossMap = new ConcurrentHashMap<>(bossDataMap);
        for(CrossTwinsBossData bossData : bossMap.values()){
            if(!bossData.getBool().equals(BigInteger.ZERO)){
                goBossIdList.add(bossData.getBossId());
            }
        }
        if(goBossIdList.size() == 0){
            return 0;
        }
        int bossId;
        if(attBossId != 0){
            bossId = attBossId;
        }else{
            int bossIndex = randomHelper.next(0,goBossIdList.size());
            bossId = goBossIdList.get(bossIndex);
        }
        CrossTwinsBossData bossData = getBossData(bossId);
        long userId = userData.getUserId();
        synchronized (getUserLock(userId)){
            if(userData.getBossId() == 0){
                userData.setBossId(bossId);
                userData.setAttackUserId(0);
                userData.setAllScore(userData.getAllScore() + userData.getAttackScore());
                userData.setAttackScore(0);
                userData.setKillUserId(0);
                userData.setKillBossUserId(0);
                userData.setKillBossId(0);
                userData.setRoomMaxBool(userData.getMaxBool());
                userData.setRoomBool(userData.getMaxBool());
                userData.setRoomAttack(userData.getMaxAttack());
                userData.setReward("");
                userData.setKillReward("");
                addNeedUpdateUserData(userData);
            }
            Map<Long, CrossTwinsUserData> userMap = bossData.getUserDataMap();
            if(!userMap.containsKey(userId)){
                userMap.put(userId,userData);
            }
            addUserToBossRoom(bossId,userId);
        }
        return bossId;
    }

    //随机攻打boss或者w
    private void pvpDebugBeat(CrossTwinsUserData userData,long attUserId){
        if(userData.getStatus() != 0 || userData.getBossId() == 0){
            return;
        }
        List<Long> randomAttackList = new ArrayList<>();
        //打boss
        randomAttackList.add(0L);
        CrossTwinsBossData bossData = getBossData(userData.getBossId());
        List<CrossTwinsUserData> userList = new ArrayList<>(bossData.getUserDataMap().values());
        for(CrossTwinsUserData user : userList){
            if(user.getUserId() == userData.getUserId() || user.getRoomBool().equals(BigInteger.ZERO)){
                continue;
            }
            randomAttackList.add(user.getUserId());
        }
        long attackUserId;
        if(attUserId == 0){
            attackUserId = randomAttackList.get(randomHelper.next(0,randomAttackList.size()));
        }else if(attUserId == 1){
            attackUserId = 1;
        }else if(randomAttackList.contains(attUserId)){
            attackUserId = attUserId;
        }else{
            attackUserId = randomAttackList.get(0);
        }
        synchronized (userData){
            long nowTime = System.currentTimeMillis();
            long oAttackUserId = userData.getAttackUserId();
            long lastAttackTime = userData.getLastAttackTime();
            long attackTime = userData.getAttackTime();
            if(attackUserId == 0L){
                userData.setStatus(1);
                userData.setAttackUserId(0);
            }else if(attackUserId != 1 && attackUserId != 0L){
                userData.setStatus(2);
                userData.setAttackUserId(attackUserId);
            }else{
                userData.setAttackUserId(0);
                userData.setStatus(0);
            }
            if(userData.getStatus() != 0){
                if(nowTime - lastAttackTime < config.getPvpAttackCd()){
                    userData.setAttackTime(lastAttackTime + config.getPvpAttackCd());
                }else{
                    userData.setAttackTime(nowTime);
                    userData.setLastAttackTime(nowTime - config.getPvpAttackCd());
                }
                addDamageRecord(userData);
            }

            changeUserPlace(userData,oAttackUserId);
            addNeedUpdateUserData(userData);
        }
    }

    public void removeDebug(long playerId) {
        debugUserMap.remove(playerId);
    }


    //优先最新一次挑战，先攻个挑战优先显示我击败的，按照获得积分，再来就是用伤害
    class DamageRecordSort implements Comparator<CrossTwinsDamageRecordData> {
        @Override
        public int compare(CrossTwinsDamageRecordData o1, CrossTwinsDamageRecordData o2) {
            if (o1.getUserNo() == o2.getUserNo()) {
                //击杀的排前面
                if(o1.isKill() && !o2.isKill()){
                    return -1;
                }
                if(o1.getScore() == o2.getScore()){
                    if(o1.getDamage().compareTo(o2.getDamage()) == 0){
                        if(o1.getStartTime() == o2.getStartTime()){
                            return 0;
                        }
                        if(o1.getStartTime() > o2.getStartTime()){
                            return -1;
                        }
                    }
                    if(o1.getDamage().compareTo(o2.getDamage()) > 0){
                        return -1;
                    }
                }
                if(o1.getScore() > o2.getScore()){
                    return -1;
                }
            }
            if (o1.getUserNo() > o2.getUserNo()) {
                return -1;
            }
            return 1;
        }
    }

    class BeDamageRecordSort implements Comparator<CrossTwinsDamageRecordData> {
        @Override
        public int compare(CrossTwinsDamageRecordData o1, CrossTwinsDamageRecordData o2) {
            if (o1.getAttackUserNo() == o2.getAttackUserNo()) {
                //击杀的排前面
                if(o1.isKill() && !o2.isKill()){
                    return -1;
                }
                if(o1.getScore() == o2.getScore()){
                    if(o1.getDamage().compareTo(o2.getDamage()) == 0){
                        if(o1.getStartTime() == o2.getStartTime()){
                            return 0;
                        }
                        if(o1.getStartTime() > o2.getStartTime()){
                            return -1;
                        }
                    }
                    if(o1.getDamage().compareTo(o2.getDamage()) > 0){
                        return -1;
                    }
                }
                if(o1.getScore() > o2.getScore()){
                    return -1;
                }
            }
            if (o1.getAttackUserNo() > o2.getAttackUserNo()) {
                return -1;
            }
            return 1;
        }
    }

    //获取战斗记录
    public void pvpGetAttackRecord(long serverId, long userId, TwinsProto.TwinsPvpGetRecordReqMsg reqMsg) {
        TwinsProto.TwinsPvpGetRecordRespMsg.Builder respMsg = TwinsProto.TwinsPvpGetRecordRespMsg.newBuilder();
        respMsg.setRet(0);
        int type = reqMsg.getType();
        int page = reqMsg.getPage();
        int pageCount = 50;
        int index = (page - 1) * pageCount;
        CrossTwinsUserData userData = getUserData(userId);
        if(userData == null){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_USER_DATA_NOT_EXIT);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_ATTACK_RECORD, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        Map<Integer,Map<Integer,CrossTwinsDamageRecordData>> recordMap = new ConcurrentHashMap<>();
        Map<Integer,Map<Integer,CrossTwinsDamageRecordData>> beRecordMap = new ConcurrentHashMap<>();
        if(type == 1){
            recordMap = userData.getAttackDamageRecordMap();
        }else if(type == 2){
            beRecordMap = userData.getBeAttackDamageRecordMap();
        }else{
            respMsg.setRet(GameErrorCode.E_TWINS_PARAMS);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_ATTACK_RECORD, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        List<CrossTwinsDamageRecordData> recordList = new ArrayList<>();
        for(Map<Integer,CrossTwinsDamageRecordData> tempMap : recordMap.values()){
            recordList.addAll(new ArrayList<>(tempMap.values()));
        }
        for(Map<Integer,CrossTwinsDamageRecordData> tempMap : beRecordMap.values()){
            recordList.addAll(new ArrayList<>(tempMap.values()));
        }
        if(type == 1){
            recordList.sort(new DamageRecordSort());
        }else if(type == 2){
            recordList.sort(new BeDamageRecordSort());
        }

        if(recordList.size() > 100){
            List<CrossTwinsDamageRecordData> tempRecordList = new ArrayList<>(recordList);
            recordList = new ArrayList<>();
            for(int i = 0; i < pageCount; i++){
                recordList.add(tempRecordList.get(i));
            }
        }

        for(int count = 0;count < pageCount; count++){
            if(index >= recordList.size()){
                break;
            }
            CrossTwinsDamageRecordData recordData = recordList.get(index);
            if(recordData.getDamage().equals(BigInteger.ZERO)){
                index++;
                continue;
            }
            respMsg.addRecord(parseTwinsPvpRecordMsg(recordData,type));
            index++;
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_ATTACK_RECORD, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //1自己打别人的2被打的
    private TwinsProto.TwinsPvpRecordMsg.Builder parseTwinsPvpRecordMsg(CrossTwinsDamageRecordData recordData,int type){
        TwinsProto.TwinsPvpRecordMsg.Builder recordMsg = TwinsProto.TwinsPvpRecordMsg.newBuilder();
        UserBaseInfo userBaseInfo = null;
        if(type == 1){
            userBaseInfo = CrossUserMgr.getUserBaseInfo(recordData.getAttackUserId());
            recordMsg.setUserId(recordData.getAttackUserId());
        }else if(type == 2){
            userBaseInfo = CrossUserMgr.getUserBaseInfo(recordData.getUserId());
            recordMsg.setUserId(recordData.getUserId());
        }
        if(userBaseInfo == null){
            return null;
        }
        recordMsg.setServerId(userBaseInfo.getServerId());
        recordMsg.setUserName(userBaseInfo.getNickName());
        recordMsg.setDecoration(userBaseInfo.getDecoration());
        recordMsg.setValue(recordData.getDamage().toString());
        recordMsg.setScore((int)recordData.getScore());
        recordMsg.setIsKill(recordData.isKill());
        return recordMsg;
    }


    //领奖
    public void pvpGetReward(long serverId, long userId, TwinsProto.TwinsPvpGetRewardReqMsg reqMsg) {
        TwinsProto.TwinsPvpGetRewardRespMsg.Builder respMsg = TwinsProto.TwinsPvpGetRewardRespMsg.newBuilder();
        respMsg.setRet(0);
        CrossTwinsUserData userData = getUserData(userId);
        if(userData == null){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_USER_DATA_NOT_EXIT);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_REWARD, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        if(StringUtils.isNullOrEmpty(userData.getReward())){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_GET_REWARD_ERR);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_REWARD, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }

        respMsg.setBossId(userData.getLastBossId());
        respMsg.setReward(userData.getReward());
        respMsg.setKillReward(userData.getKillReward());
        respMsg.setScore((int)userData.getAttackScore());
        respMsg.setKillBossNickName("");
        respMsg.setKillSelfNickName("");
        respMsg.setKillSelfBossId(0);
        if(userData.getKillUserId() != 0){
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getKillUserId());
            if(userBaseInfo != null){
                respMsg.setKillSelfNickName(userBaseInfo.getNickName());
            }
        }else if(userData.getKillBossUserId() != 0){
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getKillBossUserId());
            if(userBaseInfo != null){
                respMsg.setKillBossNickName(userBaseInfo.getNickName());
            }
        }else if(userData.getKillBossId() != 0){
            respMsg.setKillSelfBossId(userData.getKillBossId());
        }

        userData.setReward("");
        userData.setKillReward("");
        addNeedUpdateUserData(userData);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_TWINS_CROSS_GET_REWARD, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
        pvpSyncUserData(serverId,userId);
    }

    //反击玩家
    public void pvpBackBeat(long serverId, long userId, TwinsProto.TwinsPvpBackBeatReqMsg reqMsg) {
        TwinsProto.TwinsPvpBackBeatRespMsg.Builder respMsg = TwinsProto.TwinsPvpBackBeatRespMsg.newBuilder();
        respMsg.setRet(0);
        CrossTwinsUserData userData = getUserData(reqMsg.getUserId());
        if(userData == null){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_USER_DATA_NOT_EXIT);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_BACK_BEAT, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        respMsg.setBossId(userData.getBossId());
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_BACK_BEAT, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //攻击
    public void pvpAttack(long serverId, long userId, TwinsProto.TwinsPvpAttackReqMsg reqMsg) {
        TwinsProto.TwinsPvpAttackRespMsg.Builder respMsg = TwinsProto.TwinsPvpAttackRespMsg.newBuilder();
        respMsg.setRet(0);
        long nowTime = System.currentTimeMillis();
        if(!isPvpTime()){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_IN_TIME);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ATTACK, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        CrossTwinsUserData userData = getUserData(userId);
        if(userData == null){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_USER_DATA_NOT_EXIT);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ATTACK, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        if(userData.getStatus() == 0){
            //不能发挥错误码，要告诉玩家打的人已经死了
//            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_ATTACK_STATUS);
            respMsg.setBool("0");
            respMsg.setUserBool("0");
            respMsg.setAttackValue("0");
            respMsg.setScore((int)userData.getAttackScore());
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ATTACK, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        if(nowTime - userData.getLastAttackTime() < config.getPvpAttackCd()){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_ATTACK_CD);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ATTACK, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        int status = userData.getStatus();
        int bossId = userData.getBossId();
        long attackUserId = userData.getAttackUserId();
        BigInteger attackValue = BigInteger.ZERO;
        if(status == 2 && attackUserId != 0){
            CrossUserBaseInfo crossUserBaseInfo = CrossUserMgr.getCrossUserBaseInfo(userData.getUserId());
            CrossUserBaseInfo crossBeUserBaseInfo = CrossUserMgr.getCrossUserBaseInfo(userData.getAttackUserId());
            if(crossUserBaseInfo != null && crossBeUserBaseInfo != null){
                if(!StringUtils.isNullOrEmpty(crossUserBaseInfo.getUserBaseInfo().getUnionUid())
                        && !StringUtils.isNullOrEmpty(crossBeUserBaseInfo.getUserBaseInfo().getUnionUid())
                        && crossUserBaseInfo.getUserBaseInfo().getUnionUid().equals(crossBeUserBaseInfo.getUserBaseInfo().getUnionUid()) ){
                    respMsg.setRet(GameErrorCode.E_TWINS_PVP_ATTACK_SAME_UNION);
                    YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ATTACK, respMsg);
                    MessageHelper.sendPacket(serverId, userId, pbMsg);
                    return;
                }
            }
            synchronized (getUserLock(attackUserId)){
                attackValue = beatUser(userData);
                if(attackValue.compareTo(BigInteger.ZERO) > 0){
                    userData.setLastAttackTime(System.currentTimeMillis());
                }
            }
        }else if(status == 1){
            CrossTwinsBossData bossData = getBossData(userData.getBossId());
            synchronized (bossData){
                attackValue = beatBoss(userData);
                if(attackValue.compareTo(BigInteger.ZERO) > 0){
                    userData.setLastAttackTime(System.currentTimeMillis());
                }
            }
        }
        respMsg.setAttackTime(userData.getLastAttackTime());
        respMsg.setBool("0");
        respMsg.setUserBool("0");
        respMsg.setAttackValue(attackValue.toString());
        respMsg.setScore((int)userData.getAttackScore());

        if(status == 1){
            CrossTwinsBossData bossData = getBossData(bossId);
            respMsg.setBool(bossData.getBool().toString());
            if(attackValue.compareTo(BigInteger.ZERO) > 0){
                TwinsPvpConfig pvpConfig = config.getPvpConfig(bossId);
                long score = attackValue.longValue()/pvpConfig.getAttackDamage(getActivity().getBeginTime()) * pvpConfig.getAttackScore(getActivity().getBeginTime());
                respMsg.setGetScore((int)(score));
                CrossActivityLogMgr.addLogTwinsPvpBattle(
                        getActivityId(),groupId,userData.getUserId(),userData.getBossId(),userData.getAttackUserId(),
                        attackValue + "|" + bossData.getBool().toString(),respMsg.getGetScore(),respMsg.getScore(),
                        bossData.getBool().equals(BigInteger.ZERO) && attackValue.compareTo(BigInteger.ZERO) > 0 ? 1:0,
                        userData.getRoomBool().toString());
            }
        }else if(status == 2){
            CrossTwinsUserData beAttackUserData = getUserData(attackUserId);
            if(beAttackUserData != null){
                respMsg.setUserBool(beAttackUserData.getRoomBool().toString());
                //打玩家，玩家的血量变0了自己的造成的伤害不是0，表示打死了
                if(beAttackUserData.getRoomBool().equals(BigInteger.ZERO) && attackValue.compareTo(BigInteger.ZERO) > 0){
                    respMsg.setGetScore((int)(beAttackUserData.getAttackScore()*config.getPvpKillParam()/1000));
                }

                if(attackValue.compareTo(BigInteger.ZERO) > 0){
                    CrossActivityLogMgr.addLogTwinsPvpBattle(
                            getActivityId(),groupId,userData.getUserId(),userData.getBossId(),userData.getAttackUserId(),
                            attackValue + "|" + beAttackUserData.getRoomBool().toString(),respMsg.getGetScore(),respMsg.getScore(),
                            beAttackUserData.getRoomBool().equals(BigInteger.ZERO) && attackValue.compareTo(BigInteger.ZERO) > 0 ? 1:0,
                            userData.getRoomBool().toString());
                }
            }
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ATTACK, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //排序一下攻击先后顺序 小的在前面先出手
    class AttackIndexSort implements Comparator<CrossTwinsUserData> {
        @Override
        public int compare(CrossTwinsUserData o1, CrossTwinsUserData o2) {
            if (o1.getLastAttackTime() == o2.getLastAttackTime()) {
                return 0;
            }
            if (o1.getLastAttackTime() < o2.getLastAttackTime()) {
                return -1;
            }
            return 1;
        }
    }

    private BigInteger oneUserBeat(CrossTwinsUserData userData){
        synchronized (userData){
            if(userData.getStatus() == 1){
                userData.setLastAttackTime(System.currentTimeMillis());
                return beatBoss(userData);
            }else if(userData.getStatus() == 2){
                userData.setLastAttackTime(System.currentTimeMillis());
                return beatUser(userData);
            }
        }
        return BigInteger.ZERO;
    }

    private BigInteger beatUser(CrossTwinsUserData userData){
        if(userData.getAttackUserId() == 0 || userData.getStatus() != 2){
            logger.info("双骄pvp{},玩家{}攻击对象{}没了，可能死了或者玩家不打了- -"
                    ,getActivityId(),userData.getUserId(),userData.getAttackUserId());
            return BigInteger.ZERO;
        }
        CrossTwinsUserData beAttackUserData = getUserData(userData.getAttackUserId());
        if(beAttackUserData.getRoomBool().compareTo(BigInteger.ZERO) == 0){
            logger.info("双骄pvp{},玩家{}攻击对象{}已经死了- -"
                    ,getActivityId(),userData.getUserId(),userData.getAttackUserId());
            userData.setStatus(0);
            userData.setAttackUserId(0);
            return BigInteger.ZERO;
        }
        BigInteger beAttackUserBool = beAttackUserData.getRoomBool();
        BigInteger attackValue = BigInteger.ZERO;
        if(beAttackUserBool.compareTo(userData.getRoomAttack()) > 0){
            attackValue = userData.getRoomAttack();
        }else{
            attackValue = beAttackUserBool;
        }
        beAttackUserBool = beAttackUserBool.subtract(attackValue);
        //打人不加声望
//        TwinsPvpConfig pvpConfig = config.getPvpConfig(userData.getBossId());
//        long score = attackValue.longValue()/pvpConfig.getAttackDamage() * pvpConfig.getAttackScore();
//        userData.setAttackScore(userData.getAttackScore() + score);
        beAttackUserData.setRoomBool(beAttackUserBool);
        addUserAttackRecordValue(userData,attackValue);
//        addNeedSyncCondition(userData);
        addNeedUpdateUserData(userData);
        addNeedUpdateUserData(beAttackUserData);
        if(attackValue.compareTo(BigInteger.ZERO) > 0){
            makeUserAttackData(userData,attackValue);
        }
        if(beAttackUserData.getRoomBool().compareTo(BigInteger.ZERO) == 0){
            userDie(beAttackUserData,userData.getUserId());
            long addValue = beAttackUserData.getAttackScore();
            addValue = addValue*config.getPvpKillParam()/1000;
            userData.setAttackScore(userData.getAttackScore() + addValue);
            addNeedSyncCondition(userData);
        }
        return attackValue;
    }

    //打了多少伤害也要记录
    private void addUserAttackRecordValue(CrossTwinsUserData userData, BigInteger value){
        CrossTwinsBossData bossData = getBossData(userData.getBossId());
        if(bossData != null){
            Map<Integer, Map<Integer,CrossTwinsDamageRecordData>> attackValueMap = userData.getAttackDamageRecordMap();
            CrossTwinsUserData beAttackUserData = getUserData(userData.getAttackUserId());
            if(!attackValueMap.containsKey(beAttackUserData.getUserNo())){
                attackValueMap.put(beAttackUserData.getUserNo(),new ConcurrentHashMap<>());
            }
            CrossTwinsDamageRecordData damageRecordData = attackValueMap.get(beAttackUserData.getUserNo()).get(userData.getUserNo());
            if(damageRecordData == null){
                attackValueMap.get(beAttackUserData.getUserNo()).put(userData.getUserNo(),initDamageRecord(bossData,userData,beAttackUserData));
                damageRecordData = attackValueMap.get(beAttackUserData.getUserNo()).get(userData.getUserNo());
            }
            damageRecordData.setDamage(damageRecordData.getDamage().add(value));
            if(beAttackUserData.getRoomBool().equals(BigInteger.ZERO)){
                userData.setKillTimes(userData.getKillTimes() + 1);
                //死了记录一下攻击记录有击杀积分
                damageRecordData.setScore(beAttackUserData.getAttackScore()*config.getPvpKillParam()/1000);
                damageRecordData.setKill(true);

                CrossUserBaseInfo aCrossUserBaseInfo = CrossUserMgr.getCrossUserBaseInfo(userData.getUserId());
                CrossUserBaseInfo beCrossUserBaseInfo = CrossUserMgr.getCrossUserBaseInfo(beAttackUserData.getUserId());
                if(aCrossUserBaseInfo != null && beCrossUserBaseInfo != null){
                    if(userData.getKillTimes()%config.getPvpKillTimesNotice() == 0){
                        String content = WorldMessageMgr.encodeContent(aCrossUserBaseInfo.getUserBaseInfo().getNickName(),beCrossUserBaseInfo.getUserBaseInfo().getNickName(), damageRecordData.getScore(),userData.getKillTimes());
                        WorldMessageProto.WorldMessageTempMsg.Builder chatMsg = WorldMessageMgr.parseWorldMessageTempMsg(aCrossUserBaseInfo,
                                eMessageType.TwinsKillUser.getValue(), eChatContentType.Common.getContentType(), content, DateHelper.getCurrentTime(), getActivityId(), null);
                        chatMsg.setGroupId(groupId);
                        ActivityChatMgr.activityChat(getActivityId(),chatMsg.build());
                    }
                }
            }
            addNeedUpdateDamageRecordData(damageRecordData);
        }
    }

    /**
     * @return
     */
    private CrossTwinsDamageRecordData initDamageRecord(CrossTwinsBossData bossData,CrossTwinsUserData userData,CrossTwinsUserData beAttackUserData){
        CrossTwinsDamageRecordData damageRecordData = new CrossTwinsDamageRecordData();
        damageRecordData.setBossNo(bossData.getBossNo());
        damageRecordData.setActivityId(getActivityId());
        damageRecordData.setGroupId(groupId);
        damageRecordData.setBossId(bossData.getBossId());
        damageRecordData.setDamage(BigInteger.ZERO);
        //最开始的战斗时间
        damageRecordData.setStartTime(System.currentTimeMillis());
        damageRecordData.setUserNo(userData.getUserNo());
        damageRecordData.setUserId(userData.getUserId());
        if(beAttackUserData != null){
            damageRecordData.setAttackUserNo(beAttackUserData.getUserNo());
            damageRecordData.setAttackUserId(beAttackUserData.getUserId());
        }
        addNeedInsertDamageRecordData(damageRecordData);
        return damageRecordData;
    }

    //玩家死了或者boss死了之后的奖励
    private void setUserOverReward(CrossTwinsUserData userData,boolean isKill){
        TwinsPvpConfig pvpConfig = config.getPvpConfig(userData.getBossId());
        String reward = "";
        //都不满足就是最大的档位了
        String tempReward = "";
        List<Integer> scoreList = pvpConfig.getScoreList();
        List<String> rewardList = pvpConfig.getRewardList();
        for(int index = 0; index < scoreList.size() ; index++){
            tempReward = rewardList.get(index);
            if(userData.getAttackScore() <= scoreList.get(index)){
                reward = rewardList.get(index);
                break;
            }
        }
        if(StringUtils.isNullOrEmpty(reward)){
            reward = tempReward;
        }
        userData.setReward(reward);
        if(isKill){
            userData.setKillReward(pvpConfig.getRewards());
        }
        //不能移除要同步boss的最后血量,等客户端自己退出，客户端没有退出就下次进入其他房间会退出或者掉线
//        enterBossRoomMap.get(userData.getBossId()).remove(userData.getUserId());
        //???
        CrossTwinsBossData bossData = getBossData(userData.getBossId());
        bossData.getUserDataMap().remove(userData.getUserId());
        long oAttackUserId = userData.getAttackUserId();
        userData.setUserNo(userNo.getAndIncrement());
        userData.setBossId(0);
        userData.setStatus(0);
        userData.setAttackUserId(0);
        userData.setKillTimes(0);
        userData.setDieTime(System.currentTimeMillis());
        changeUserPlace(userData,oAttackUserId);
        addNeedUpdateUserData(userData);
    }

    //玩家被打死了
    private void userDie(CrossTwinsUserData beAttackUserData,long killUserId){
        beAttackUserData.setLastBossId(beAttackUserData.getBossId());
        beAttackUserData.setKillUserId(killUserId);
        //不是玩家杀了他就是boss杀了他
        if(killUserId == 0){
            beAttackUserData.setKillBossId(beAttackUserData.getBossId());
        }
        //死了发奖励，通知玩家可以领奖了
        setUserOverReward(beAttackUserData,false);
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(beAttackUserData.getUserId());
        if(userBaseInfo != null){
            pvpSyncUserData(userBaseInfo.getServerId(),beAttackUserData.getUserId());
        }
        //双重保险，可能点太快变换太快了
        CrossTwinsUserData killUserData = getUserData(killUserId);
        if(killUserData != null){
            killUserData.setStatus(0);
            killUserData.setAttackUserId(0);
            beAttackUserMap.get(beAttackUserData.getUserId()).remove(killUserData.getUserId());
            attackUserMap.remove(killUserData.getUserId());
        }
        //所有在打他的人变成打空气
        if(beAttackUserMap.containsKey(beAttackUserData.getUserId())){
            for(CrossTwinsUserData attackUserData : beAttackUserMap.get(beAttackUserData.getUserId()).values()){
                attackUserData.setStatus(0);
                attackUserData.setAttackUserId(0);
                beAttackUserMap.get(beAttackUserData.getUserId()).remove(attackUserData.getUserId());
                attackUserMap.remove(attackUserData.getUserId());
            }
        }else{
            logger.error("巅峰{}移除被攻击对象中没有攻击玩家",getActivityId());
        }
    }

    private BigInteger beatBoss(CrossTwinsUserData userData){
        if(userData.getStatus() != 1){
            logger.error("双骄pvp{},玩家{}攻击不是boss了- -"
                    ,getActivityId(),userData.getUserId());
            return BigInteger.ZERO;
        }
        CrossTwinsBossData bossData = getBossData(userData.getBossId());
        if(bossData.getBool().compareTo(BigInteger.ZERO) == 0){
            logger.info("双骄pvp{},玩家{}攻击Boss{}已经死了- -"
                    ,getActivityId(),userData.getUserId(),userData.getBossId());
            return BigInteger.ZERO;
        }
        TwinsPvpConfig pvpConfig = config.getPvpConfig(userData.getBossId());
        BigInteger bossBool = bossData.getBool();
        BigInteger userBool = userData.getRoomBool();
        BigInteger attackBossValue = BigInteger.ZERO;
        //玩家被boss回击伤害
        BigInteger attackUserValue = BigInteger.ZERO;
        BigInteger bossAttack = new BigInteger(pvpConfig.getBossAttack(getActivity().getBeginTime()));
        if(bossBool.compareTo(userData.getRoomAttack()) > 0){
            attackBossValue = userData.getRoomAttack();
            //boss没有死，对玩家造成反击
            if(userBool.compareTo(bossAttack) > 0){
                attackUserValue = bossAttack;
            }else{
                attackUserValue = userBool;
            }
        }else{
            attackBossValue = bossBool;
        }
        bossBool = bossBool.subtract(attackBossValue);
        userBool = userBool.subtract(attackUserValue);
        //加多少声望
        long score = attackBossValue.longValue()/pvpConfig.getAttackDamage(getActivity().getBeginTime()) * pvpConfig.getAttackScore(getActivity().getBeginTime());
        userData.setAttackScore(userData.getAttackScore() + score);
        userData.setRoomBool(userBool);
        bossData.setBool(bossBool);
        addNeedSyncCondition(userData);
        addNeedUpdateUserData(userData);
        addNeedUpdateBossData(bossData);
        makeBossAttackData(userData,attackUserValue,attackBossValue);
        if(bossData.getBool().compareTo(BigInteger.ZERO) == 0){
            bossDie(bossData,userData);
        }
        if(userData.getRoomBool().compareTo(BigInteger.ZERO) == 0){
            userDie(userData,0);
        }
        return attackBossValue;
    }

    //生成攻击同步给客户端
    private void makeBossAttackData(CrossTwinsUserData userData,BigInteger userDamage,BigInteger bossDamage){
        //玩家不在场景，不生成战斗中间数据
        if(!enterBossRoomMap.containsKey(userData.getBossId())
                || !enterBossRoomMap.get(userData.getBossId()).contains(userData.getUserId())){
            return;
        }
        if(userDamage.compareTo(BigInteger.ZERO) > 0){
            CrossTwinsBeatDamageData userDamageData = new CrossTwinsBeatDamageData();
            userDamageData.setActivityId(getActivityId());
            userDamageData.setUserId(userData.getUserId());
            userDamageData.setBossId(userData.getBossId());
            userDamageData.setAttackUserId(0);
            userDamageData.setDamage(userDamage);
            userDamageData.setUserBool(userData.getRoomBool());
            if(userDamageMap.containsKey(userDamageData.getUserId())) {
                synchronized (userDamageMap.get(userDamageData.getUserId())){
                    userDamageMap.get(userDamageData.getUserId()).add(userDamageData);
                }
            }
        }
        if(bossDamage.compareTo(BigInteger.ZERO) > 0){
            CrossTwinsBeatDamageData bossDamageData = new CrossTwinsBeatDamageData();
            bossDamageData.setActivityId(getActivityId());
            bossDamageData.setUserId(userData.getUserId());
            bossDamageData.setBossId(userData.getBossId());
            bossDamageData.setAttackUserId(0);
            bossDamageData.setDamage(bossDamage);
            bossDamageData.setUserBool(userData.getRoomBool());
            if(bossDamageMap.containsKey(userData.getBossId())){
                List<CrossTwinsBeatDamageData> damageList = bossDamageMap.get(userData.getBossId());
                synchronized (damageList){
                    bossDamageMap.get(userData.getBossId()).add(bossDamageData);
                }
            }
        }
    }

    //同步记录用到
    private void makeUserAttackData(CrossTwinsUserData userData,BigInteger userDamage){
        //玩家不在场景，不生成战斗中间数据
        if(!enterBossRoomMap.get(userData.getBossId()).contains(userData.getUserId())){
            return;
        }
        if(userDamage.compareTo(BigInteger.ZERO) > 0){
            CrossTwinsUserData beAttackUserData = getUserData(userData.getAttackUserId());
            CrossTwinsBeatDamageData userDamageData = new CrossTwinsBeatDamageData();
            userDamageData.setActivityId(getActivityId());
            userDamageData.setUserId(beAttackUserData.getUserId());
            userDamageData.setBossId(beAttackUserData.getBossId());
            userDamageData.setAttackUserId(userData.getUserId());
            userDamageData.setDamage(userDamage);
            userDamageData.setUserBool(beAttackUserData.getRoomBool());
            if(userDamageMap.containsKey(userDamageData.getUserId())) {
                synchronized (userDamageMap.get(userDamageData.getUserId())){
                    userDamageMap.get(userDamageData.getUserId()).add(userDamageData);
                }
            }
        }
    }

    /**
     * @param bossData
     * @param killUser boss被谁干死了
     */
    private void bossDie(CrossTwinsBossData bossData,CrossTwinsUserData killUser){
        bossData.setBool(BigInteger.ZERO);
        Map<Long, CrossTwinsUserData> userDataMap = new ConcurrentHashMap<>(bossData.getUserDataMap());
        for(CrossTwinsUserData userData : userDataMap.values()){
            if(killUser != null){
                userData.setKillBossUserId(killUser.getUserId());
            }
            if(killUser != null && userData.getUserId() == killUser.getUserId()){
                setUserOverReward(userData,true);
            }else{
                setUserOverReward(userData,false);
            }
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
            if(userBaseInfo != null){
                pvpSyncUserData(userBaseInfo.getServerId(),userData.getUserId());
            }
        }
        bossData.setDieTime(System.currentTimeMillis());
        //不能全部移除了，客户端要同步一次没血了他才会，留着等客户端自己发退出房间消息，要是客户端没发就只能等掉线或者boss原地复活或者玩家进入其他地方
//        enterBossRoomMap.get(bossData.getBossId()).clear();
        if(killUser != null){
            CrossUserBaseInfo crossUserBaseInfo = CrossUserMgr.getCrossUserBaseInfo(killUser.getUserId());
            if(crossUserBaseInfo != null){
                String content = WorldMessageMgr.encodeContent(crossUserBaseInfo.getUserBaseInfo().getNickName(), bossData.getBossId());
                WorldMessageProto.WorldMessageTempMsg.Builder chatMsg = WorldMessageMgr.parseWorldMessageTempMsg(crossUserBaseInfo,
                        eMessageType.TwinsKillBoss.getValue(), eChatContentType.Common.getContentType(), content, DateHelper.getCurrentTime(), getActivityId(), null);
                chatMsg.setGroupId(groupId);
                ActivityChatMgr.activityChat(getActivityId(),chatMsg.build());
            }
        }
    }

    //生成boss
    private CrossTwinsBossData initBoss(TwinsPvpConfig bossConfig,long bossStartTime){
        CrossTwinsBossData bossData = new CrossTwinsBossData();
        bossData.setActivityId(getActivityId());
        bossData.setGroupId(groupId);
        bossData.setBossNo(bossNo.getAndIncrement());
        bossData.setBossId(bossConfig.getId());
        bossData.setBool(new BigInteger(bossConfig.getBossBool(getActivity().getBeginTime())));
        bossData.setStartTime(bossStartTime);
        bossData.setDieTimes(0);
        bossData.setDieTime(0);
        bossData.setUserDataMap(new ConcurrentHashMap<>());
        bossDataMap.put(bossData.getBossId(),bossData);
        addNeedInsertBossData(bossData);
        if(!bossDamageMap.containsKey(bossConfig.getId())){
            bossDamageMap.put(bossConfig.getId(),new ArrayList<>());
        }
        if(enterBossRoomMap.containsKey(bossData.getBossId())){
            List<Long> userIdList = enterBossRoomMap.get(bossData.getBossId());
            synchronized (userIdList){
                userIdList.clear();
            }
        }
        return bossData;
    }
    //生成boss
    private void checkBoss(long nowTime){
        if(!isPvpTime()){
            return;
        }
        long bossStartTime = DateHelper.getTodayZeroTimeStamp() + config.getPvpDayStartTime();
        long bossEndTime = DateHelper.getTodayZeroTimeStamp() + config.getPvpDayEndTime();
        Map<Integer, TwinsPvpConfig> pvpBossConfigMap = config.getPvpConfigMap();
        //初始化
        if(pvpBossConfigMap.size() != bossDataMap.size()){
            for(TwinsPvpConfig bossConfig : pvpBossConfigMap.values()){
                if(!bossDataMap.containsKey(bossConfig.getId())){
                    initBoss(bossConfig,bossStartTime);
                }
            }
        }
        for(CrossTwinsBossData bossData : bossDataMap.values()){
            TwinsPvpConfig pvpConfig = pvpBossConfigMap.get(bossData.getBossId());
            if(bossData.getBool().equals(BigInteger.ZERO) && nowTime - bossData.getDieTime() > (long)1000 * pvpConfig.getRefreshTime()){
                initBoss(pvpConfig,bossStartTime);
            }
        }
    }

    public CrossTwinsUserData getUserData(long userId){
        if(userDataMap.containsKey(userId)){
            return userDataMap.get(userId);
        }
        return null;
    }

    public CrossTwinsBossData getBossData(int bossId){
        if(bossDataMap.containsKey(bossId)){
            return bossDataMap.get(bossId);
        }
        return null;
    }

    //每一个登录的用户都初始化他的数据
    public CrossTwinsUserData initUserData(long userId, BigInteger maxBool, BigInteger maxAttack){
        synchronized (getUserLock(userId)){
            if(!userDataMap.containsKey(userId)){
                CrossTwinsUserData userData = new CrossTwinsUserData();
                userData.setActivityId(getActivityId());
                userData.setGroupId(groupId);
                userData.setMaxBool(maxBool);
                userData.setHp(config.getPvpHpMax());
                userData.setHpTime(DateHelper.getTodayZeroTimeStamp());
                userData.setUserNo(userNo.getAndIncrement());
                userData.setUserId(userId);
                userDataMap.put(userId,userData);
                if(!beAttackUserMap.containsKey(userId)){
                    beAttackUserMap.put(userId,new ConcurrentHashMap<>());
                }
                if(!userDamageMap.containsKey(userId)){
                    userDamageMap.put(userId,new ArrayList<>());
                }
                changeUserPlace(userData,0);
                addNeedInsertUserData(userData);
            }
            userDataMap.get(userId).setMaxBool(maxBool);
            userDataMap.get(userId).setMaxAttack(maxAttack);
            addNeedUpdateUserData(userDataMap.get(userId));
        }
        return userDataMap.get(userId);
    }

    public void pvpEnterMain(long serverId, long userId, TwinsProto.TwinsPvpEnterMainReqMsg reqMsg) {
        TwinsProto.TwinsPvpEnterMainResMsg.Builder respMsg = TwinsProto.TwinsPvpEnterMainResMsg.newBuilder();
        respMsg.setRet(0);
        CrossTwinsUserData userData = getUserData(userId);
        if(userData != null){
            respMsg.setAttackBossId(userData.getBossId());
        }
        for(CrossTwinsBossData bossData : bossDataMap.values()){
            TwinsProto.TwinsPvpBossMsg.Builder bossMsg = TwinsProto.TwinsPvpBossMsg.newBuilder();
            bossMsg.setBossId(bossData.getBossId());
            bossMsg.setBool(bossData.getBool().toString());
            bossMsg.setDieTime(bossData.getDieTime());
            respMsg.addBoss(bossMsg);
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_MAIN, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }


    private boolean isPvpTime(){
        long nowTime = System.currentTimeMillis();
        long startTime = DateHelper.getTodayZeroTimeStamp() + config.getPvpDayStartTime();
        long endTime = DateHelper.getTodayZeroTimeStamp() + config.getPvpDayEndTime();
        if(nowTime < startTime || nowTime > endTime){
            return false;
        }
        return true;
    }

    public void pvpEnterBoss(long serverId, long userId, TwinsProto.TwinsPvpEnterBossReqMsg reqMsg) {
        TwinsProto.TwinsPvpEnterBossRespMsg.Builder respMsg = TwinsProto.TwinsPvpEnterBossRespMsg.newBuilder();
        respMsg.setRet(0);
        if(!isPvpTime()){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_IN_TIME);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_BOSS, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        if(!bossDataMap.containsKey(reqMsg.getBossId())){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_BOSS_NOT_EXIT);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_BOSS, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        CrossTwinsUserData userData = getUserData(userId);
        if(userData == null || (userData.getBossId() != 0 && userData.getBossId() != reqMsg.getBossId())){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_IN_OTHER_ROOM);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_BOSS, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        if(userData.getHp() <= 0 && userData.getBossId() == 0){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_HP_NOT_ENOUGH);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_BOSS, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        if(System.currentTimeMillis() - userData.getDieTime() < DateHelper.SECOND_MILLIONS * 5){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_BACK_ROOM_CD);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_BOSS, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        if(!StringUtils.isNullOrEmpty(userData.getReward())){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_GET_REWARD);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_BOSS, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }

        CrossTwinsBossData bossData = bossDataMap.get(reqMsg.getBossId());
        if(bossData.getBool().equals(BigInteger.ZERO)){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_BACK_ROOM_CD);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_BOSS, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }

        TwinsProto.TwinsPvpBossMsg.Builder bossMsg = TwinsProto.TwinsPvpBossMsg.newBuilder();
        bossMsg.setBossId(bossData.getBossId());
        bossMsg.setBool(bossData.getBool().toString());
        bossMsg.setDieTime(bossData.getDieTime());
        respMsg.setBoss(bossMsg);

        synchronized (getUserLock(userId)){
            //已经进入过房间了
            if(userData.getBossId() == 0){
                userData.setBossId(reqMsg.getBossId());
                //上一场的之前的保留着，领取奖励的时候要用
                userData.setAttackUserId(0);
                //积分合并
                userData.setAllScore(userData.getAllScore() + userData.getAttackScore());
                userData.setAttackScore(0);
                userData.setKillUserId(0);
                userData.setKillBossUserId(0);
                userData.setKillBossId(0);
                userData.setRoomMaxBool(userData.getMaxBool());
                userData.setRoomBool(userData.getMaxBool());
                userData.setRoomAttack(userData.getMaxAttack());
                userData.setHp(userData.getHp() - 1);
                addNeedUpdateUserData(userData);
            }
            Map<Long, CrossTwinsUserData> userMap = bossData.getUserDataMap();
            if(!userMap.containsKey(userId)){
                userMap.put(userId,userData);
            }
            addUserToBossRoom(reqMsg.getBossId(),userId);
        }

        List<CrossTwinsUserData> nearbyUserList = getNearByUser(reqMsg.getBossId(),userId);
        for(CrossTwinsUserData twinsUserData : nearbyUserList){
            TwinsProto.TwinsPvpUserMsg.Builder userMsg = parseTwinsPvpUserMsg(twinsUserData);
            if(userMsg != null){
                respMsg.addUser(userMsg);
            }
        }
        respMsg.setAttackTime(userData.getLastAttackTime());
        respMsg.setBossId(0);
        respMsg.setAttackUserId(0);
        if(userData.getStatus() == 1){
            respMsg.setBossId(userData.getBossId());
        }else if(userData.getStatus() == 2){
            respMsg.setAttackUserId(userData.getAttackUserId());
        }
        respMsg.setScore((int)userData.getAttackScore());

       YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_ENTER_BOSS, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
        pvpSyncUserData(serverId,userId);
    }

    //获取玩家附近的20个玩家
    //显示规则 显示自己，自己当前攻击的这里最多两个 2
    //保底显示攻击自己的两个人 2
    //保底显示攻击BOSS 不是自己商会的两个人 2
    //保底显示自己商会的两个人 2
    //保底显示未攻击的两个人 2
    //不足的人数安卓上面顺序补充满，直接有一条可以补满的直接补满
    //相同类型的人优先显示击杀声望分数高的玩家
    private List<CrossTwinsUserData> getNearByUser(int bossId,long userId){
        List<CrossTwinsUserData> nearbyList = new ArrayList<>();
        List<CrossTwinsUserData> nearByUserList = new ArrayList<>();
        CrossTwinsUserData selfUserData = getUserData(userId);
        nearByUserList.add(selfUserData);
        if(selfUserData.getAttackUserId() != 0){
            nearByUserList.add(getUserData(selfUserData.getAttackUserId()));
        }
        //攻击自己的
        List<CrossTwinsUserData> attackUserList = new ArrayList<>();
        //攻击BOSS 不是自己商会的
        List<CrossTwinsUserData> attackBossNotSameUnionList = new ArrayList<>();
        //自己商会的
        List<CrossTwinsUserData> sameUnionList = new ArrayList<>();
        //未攻击的
        List<CrossTwinsUserData> noAttackList = new ArrayList<>();

        CrossTwinsBossData bossData = getBossData(bossId);
        if(bossData == null){
            logger.error("绝代双骄{}，{}用户没有boss信息发送了空的附近玩家",getActivityId(),userId);
            return nearbyList;
        }
        UserBaseInfo selfBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if(selfBaseInfo == null){
            logger.error("绝代双骄{}，{}用户没有用户基础信息发送了空的附近玩家",getActivityId(),userId);
            return nearbyList;
        }
        for(CrossTwinsUserData userData : bossData.getUserDataMap().values()){
            if(userData.getUserId() == selfUserData.getAttackUserId())continue;
            if(userData.getUserId() == userId || userData.getRoomBool().equals(BigInteger.ZERO))continue;
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
            if(userBaseInfo == null)continue;
            if(userData.getAttackUserId() == userId){
                attackUserList.add(userData);
                continue;
            }
            if(selfBaseInfo.getUnionUid().equals(userBaseInfo.getUnionUid())){
                sameUnionList.add(userData);
                continue;
            }
            if(!selfBaseInfo.getUnionUid().equals(userBaseInfo.getUnionUid())){
                attackBossNotSameUnionList.add(userData);
                continue;
            }
            if(userData.getStatus() == 0){
                noAttackList.add(userData);
                continue;
            }
        }

        attackUserList.sort(new UserScoreSort());
        attackBossNotSameUnionList.sort(new UserScoreSort());
        sameUnionList.sort(new UserScoreSort());
        noAttackList.sort(new UserScoreSort());

        //全部数据20条
        int count = 20;
        //四个表保底多少个
        int list1Count = 2;
        int list2Count = 2;
        int list3Count = 2;
        int list4Count = 2;
        putCountUser(list1Count,attackUserList,nearByUserList);
        putCountUser(list2Count,attackBossNotSameUnionList,nearByUserList);
        putCountUser(list3Count,sameUnionList,nearByUserList);
        putCountUser(list4Count,noAttackList,nearByUserList);

        if (nearByUserList.size() < count){
            putCountUser(count - nearByUserList.size(),attackUserList,nearByUserList);
        }
        if (nearByUserList.size() < count){
            putCountUser(count - nearByUserList.size(),attackBossNotSameUnionList,nearByUserList);
        }
        if (nearByUserList.size() < count){
            putCountUser(count - nearByUserList.size(),sameUnionList,nearByUserList);
        }
        if (nearByUserList.size() < count){
            putCountUser(count - nearByUserList.size(),noAttackList,nearByUserList);
        }
        nearbyList.addAll(nearByUserList);
        return nearbyList;
    }

    //把对应个数的玩家放进去
    private void putCountUser(int listCount,List<CrossTwinsUserData> list,List<CrossTwinsUserData> nearByUserList){
        for(int i = listCount; i > 0; i--){
            if(list.size() == 0){
                break;
            }
            CrossTwinsUserData userData = list.get(0);
            list.remove(0);
            nearByUserList.add(userData);
        }
    }


    class UserScoreSort implements Comparator<CrossTwinsUserData> {
        @Override
        public int compare(CrossTwinsUserData o1, CrossTwinsUserData o2) {
            if (o1.getAttackScore() == o2.getAttackScore()) {
                return 0;
            }
            if (o1.getAttackScore() > o2.getAttackScore()) {
                return -1;
            }
            return 1;
        }
    }

    //获取附近玩家
    public void pvpGetNearbyUser(long serverId, long userId, TwinsProto.TwinsPvpGetUserReqMsg reqMsg){
        int maxReturnNum = 50;
        TwinsProto.TwinsPvpGetUserRespMsg.Builder respMsg = TwinsProto.TwinsPvpGetUserRespMsg.newBuilder();
        respMsg.setRet(0);
        int i = 0;
        List<CrossTwinsUserData> retUserDataList = new ArrayList<>();
        CrossTwinsUserData selfUserData = getUserData(userId);
        if(selfUserData.getBossId() == 0){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_ENTER_BOSS_ROOM);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_USER, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        /*//可能客户端没有请求在boss房间或者没收到，其他操作添加以下玩家，才会同步附近的人
        addUserToBossRoom(selfUserData.getBossId(),userId);*/
        retUserDataList.add(selfUserData);
        i++;
        if(attackUserMap.containsKey(userId)){
            CrossTwinsUserData beAttackUserData = getUserData(attackUserMap.get(userId).getAttackUserId());
            retUserDataList.add(beAttackUserData);
            i++;
        }
        if(beAttackUserMap.containsKey(userId)){
            Map<Long,CrossTwinsUserData> attackUserMap = new ConcurrentHashMap<>(beAttackUserMap.get(userId));
            for(CrossTwinsUserData attackUserData : attackUserMap.values()){
                retUserDataList.add(attackUserData);
                i++;
                if(i > maxReturnNum){
                    break;
                }
            }
        }
        if(i < maxReturnNum){
            CrossTwinsBossData bossData = bossDataMap.get(reqMsg.getBossId());
            if(bossData == null)return;
            for(CrossTwinsUserData userData : bossData.getUserDataMap().values()){
                if(!retUserDataList.contains(userData)){
                    retUserDataList.add(userData);
                    i++;
                    if(i >= maxReturnNum){
                        break;
                    }
                }
            }
        }
        //第一个加一下自己，客户端需要
        retUserDataList.remove(selfUserData);
        TwinsProto.TwinsPvpUserSearchMsg.Builder selfMsg = parseTwinsPvpUserSearchMsg(selfUserData.getUserNo(),selfUserData);
        if(selfMsg != null){
            respMsg.addUser(selfMsg);
        }
        for(CrossTwinsUserData userData : retUserDataList){
            TwinsProto.TwinsPvpUserSearchMsg.Builder msg = parseTwinsPvpUserSearchMsg(selfUserData.getUserNo(),userData);
            if(msg != null){
                respMsg.addUser(msg);
            }
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_GET_USER, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    public void pvpLeaveBoss(long serverId, long userId, TwinsProto.CrossTwinsLeaveRoomMsg reqMsg) {
        TwinsProto.TwinsPvpLeaveBossRespMsg.Builder respMsg = TwinsProto.TwinsPvpLeaveBossRespMsg.newBuilder();
        respMsg.setRet(0);
        removeUserFromBossRoom(reqMsg.getUserIdList());
        if(userId > 0){
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_LEAVE_BOSS, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
        }
    }

    private TwinsProto.TwinsPvpUserMsg.Builder parseTwinsPvpUserMsg(CrossTwinsUserData twinsUserData){
        TwinsProto.TwinsPvpUserMsg.Builder userMsg = TwinsProto.TwinsPvpUserMsg.newBuilder();
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(twinsUserData.getUserId());
        if(userBaseInfo != null){
            userMsg.setUserId(twinsUserData.getUserId());
            userMsg.setNickName(userBaseInfo.getNickName());
            userMsg.setUnionId(userBaseInfo.getUnionUid());
            userMsg.setDecoration(userBaseInfo.getDecoration());
            userMsg.setMaxBool(twinsUserData.getRoomMaxBool().toString());
            userMsg.setBool(twinsUserData.getRoomBool().toString());
            userMsg.setAttack(twinsUserData.getRoomAttack().toString());
            userMsg.setAttackScore((int)twinsUserData.getAttackScore());
            userMsg.setUnionId(userBaseInfo.getUnionUid());
            userMsg.setAttackUserId(twinsUserData.getAttackUserId());
            return userMsg;
        }
        return null;
    }

    public boolean save() {
        if (drawData.isInsertOption()) {
            TwinsBusiness.addCrossTwinsDrawData(drawData);
        } else if (drawData.isUpdateOption()) {
            TwinsBusiness.updateCrossTwinsDrawData(drawData);
        }

        List<CrossTwinsBossData> tempNeedInsertBossData = new ArrayList<>();
        if(needInsertBossData.size() > 0){
            synchronized (needInsertBossData){
                tempNeedInsertBossData = new ArrayList<>(needInsertBossData);
                needInsertBossData.clear();
            }
        }
        if(tempNeedInsertBossData.size() > 0){
            TwinsBusiness.addBossDataList(tempNeedInsertBossData);
        }


        List<CrossTwinsBossData> tempNeedUpdateBossData = new ArrayList<>();
        if(needUpdateBossData.size() > 0){
            synchronized (needUpdateBossData){
                tempNeedUpdateBossData = new ArrayList<>(needUpdateBossData);
                needUpdateBossData.clear();
            }
        }
        if(tempNeedUpdateBossData.size() > 0){
            TwinsBusiness.updateBossDataList(tempNeedUpdateBossData);
        }


        List<CrossTwinsUserData> tempNeedInsertUserData = new ArrayList<>();
        if(needInsertUserData.size() > 0){
            synchronized (needInsertUserData){
                tempNeedInsertUserData = new ArrayList<>(needInsertUserData);
                needInsertUserData.clear();
            }
        }
        if(tempNeedInsertUserData.size() > 0){
            TwinsBusiness.addUserDataList(tempNeedInsertUserData);
        }


        List<CrossTwinsUserData> tempNeedUpdateUserData = new ArrayList<>();
        if(needUpdateUserData.size() > 0){
            synchronized (needUpdateUserData){
                tempNeedUpdateUserData = new ArrayList<>(needUpdateUserData);
                needUpdateUserData.clear();
            }
        }
        if(tempNeedUpdateUserData.size() > 0){
            TwinsBusiness.updateUserDataList(tempNeedUpdateUserData);
        }


        List<CrossTwinsDamageRecordData> tempNeedInsertDamageRecordData = new ArrayList<>();
        if(needInsertDamageRecordData.size() > 0){
            synchronized (needInsertDamageRecordData){
                tempNeedInsertDamageRecordData = new ArrayList<>(needInsertDamageRecordData);
                needInsertDamageRecordData.clear();
            }
        }
        if(tempNeedInsertDamageRecordData.size() > 0){
            TwinsBusiness.addDamageRecordDataList(tempNeedInsertDamageRecordData);
        }


        List<CrossTwinsDamageRecordData> tempNeedUpdateDamageRecordData = new ArrayList<>();
        if(needUpdateDamageRecordData.size() > 0){
            synchronized (needUpdateDamageRecordData){
                tempNeedUpdateDamageRecordData = new ArrayList<>(needUpdateDamageRecordData);
                needUpdateDamageRecordData.clear();
            }
        }
        if(tempNeedUpdateDamageRecordData.size() > 0){
            TwinsBusiness.updateDamageRecordDataList(tempNeedUpdateDamageRecordData);
        }
        return true;
    }

    //玩家操作了后改变玩家的位置,在打别人的位置和在被打的位置，或者没动静的位置
    private void changeUserPlace(CrossTwinsUserData userData,long oAttackUserId){
        if(userData.getStatus() == 2){
            if(!beAttackUserMap.containsKey(userData.getAttackUserId())){
                synchronized (beAttackUserMap){
                    if(!beAttackUserMap.containsKey(userData.getAttackUserId())){
                        beAttackUserMap.put(userData.getAttackUserId(),new ConcurrentHashMap<>());
                    }
                }
            }
            beAttackUserMap.get(userData.getAttackUserId()).put(userData.getUserId(),userData);
            attackUserMap.put(userData.getUserId(),userData);
            wanderUserMap.remove(userData.getUserId());
        }else if(userData.getStatus() == 1){
            wanderUserMap.remove(userData.getUserId());
            attackUserMap.remove(userData.getUserId(),userData);
        }else{
            wanderUserMap.put(userData.getUserId(),userData);
            attackUserMap.remove(userData.getUserId(),userData);
        }
        //切同一个对象
        if(oAttackUserId != 0 && oAttackUserId != userData.getAttackUserId()){
            beAttackUserMap.get(oAttackUserId).remove(userData.getUserId());
        }
    }

    private void addUserToBossRoom(int bossId,long userId){
        if(!enterBossRoomMap.containsKey(bossId)){
            synchronized (enterBossRoomMap){
                if(!enterBossRoomMap.containsKey(bossId)){
                    enterBossRoomMap.put(bossId,new ArrayList<>());
                }
            }
        }
        //其他房间的移除掉，可能掉线了什么乱七八糟导致在两个房间
        for(int gameBossId : enterBossRoomMap.keySet()){
            List<Long> userIdList = enterBossRoomMap.get(gameBossId);
            synchronized (userIdList){
                userIdList.remove(userId);
                if(bossId != gameBossId){
                    CrossTwinsBossData bossData = getBossData(gameBossId);
                    if(bossData != null){
                        bossData.getUserDataMap().remove(userId);
                    }
                }
            }
        }
        if(!enterBossRoomMap.get(bossId).contains(userId)){
            List<Long> userIdList = enterBossRoomMap.get(bossId);
            synchronized (userIdList){
                userIdList.add(userId);
            }
        }
    }

    public void pvpBeat(long serverId, long userId, TwinsProto.TwinsPvpBeatReqMsg reqMsg) {
        TwinsProto.TwinsPvpBeatRespMsg.Builder respMsg = TwinsProto.TwinsPvpBeatRespMsg.newBuilder();
        respMsg.setRet(0);
        if(!isPvpTime()){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_IN_TIME);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_BEAT, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        CrossTwinsUserData userData = getUserData(userId);
        if(userData == null){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_USER_DATA_NOT_EXIT);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_BEAT, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        if(userData.getBossId() == 0){
            respMsg.setRet(GameErrorCode.E_TWINS_PVP_NOT_ENTER_BOSS_ROOM);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_BEAT, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        //错了，是请求的人不在同一个房间
        if(reqMsg.getUserId() != 0){
            CrossTwinsUserData attackUserData = getUserData(reqMsg.getUserId());
            if(attackUserData.getBossId() != userData.getBossId()){
                logger.info("双骄{}，数据出现异常，打不在一个房间的玩家userId:{},attackUserId{}",getActivityId(),userData.getUserId(),reqMsg.getUserId());
                respMsg.setRet(GameErrorCode.E_TWINS_PVP_USER_DIE);
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_BEAT, respMsg);
                MessageHelper.sendPacket(serverId, userId, pbMsg);
            }
        }
        if(reqMsg.getUserId() != 0){
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
            UserBaseInfo beUserBaseInfo = CrossUserMgr.getUserBaseInfo(reqMsg.getUserId());
            if(userBaseInfo != null && beUserBaseInfo != null){
                if(!StringUtils.isNullOrEmpty(userBaseInfo.getUnionUid())
                        && !StringUtils.isNullOrEmpty(beUserBaseInfo.getUnionUid())
                        && userBaseInfo.getUnionUid().equals(beUserBaseInfo.getUnionUid()) ){
                    respMsg.setRet(GameErrorCode.E_TWINS_PVP_ATTACK_SAME_UNION);
                    YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_BEAT, respMsg);
                    MessageHelper.sendPacket(serverId, userId, pbMsg);
                    return;
                }
            }
        }


        synchronized (userData){
            long nowTime = System.currentTimeMillis();
            long oAttackUserId = userData.getAttackUserId();
            long lastAttackTime = userData.getLastAttackTime();
            long attackTime = userData.getAttackTime();
            if(reqMsg.getBossId() != 0){
                userData.setAttackUserId(0);
                userData.setStatus(1);
            }else if(reqMsg.getUserId() != 0){
                userData.setStatus(2);
                userData.setAttackUserId(reqMsg.getUserId());
            }else{
                userData.setAttackUserId(0);
                userData.setStatus(0);
            }
            if(userData.getStatus() != 0){
                if(nowTime - lastAttackTime < config.getPvpAttackCd()){
                    userData.setAttackTime(lastAttackTime + config.getPvpAttackCd());
                }else{
                    userData.setAttackTime(nowTime);
                    userData.setLastAttackTime(nowTime - config.getPvpAttackCd());
                }
                addDamageRecord(userData);
            }

            changeUserPlace(userData,oAttackUserId);
            addNeedUpdateUserData(userData);


            List<CrossTwinsUserData> nearbyUserList = getNearByUser(userData.getBossId(),userId);
            for(CrossTwinsUserData nearbyUserData : nearbyUserList){
                TwinsProto.TwinsPvpUserMsg.Builder userMsg = parseTwinsPvpUserMsg(nearbyUserData);
                if(userMsg != null){
                    respMsg.addUser(userMsg);
                }
            }
            respMsg.setLastAttackTime(userData.getLastAttackTime());
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_TWINS_PVP_BEAT, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
        }
    }

    //添加boss的伤害记录或者玩家的伤害记录
    private void addDamageRecord(CrossTwinsUserData userData){
        CrossTwinsBossData bossData = getBossData(userData.getBossId());
        if(userData.getStatus() == 1){
            if(!bossData.getDamageRecordMap().containsKey(userData.getUserId())){
                bossData.getDamageRecordMap().put(userData.getUserId(),initDamageRecord(bossData,userData,null));
            }
        }else if(userData.getStatus() == 2){
            //按照userNo来记录数据的，两个人的userNo在一起才是唯一的一条记录
            CrossTwinsUserData beAttackUserData = getUserData(userData.getAttackUserId());
            if(beAttackUserData == null)return;
            //会并发
            int beUserNo = beAttackUserData.getUserNo();
            if(!userData.getAttackDamageRecordMap().containsKey(beUserNo)){
                userData.getAttackDamageRecordMap().put(beUserNo,new ConcurrentHashMap<>());
            }
            if(!userData.getAttackDamageRecordMap().get(beUserNo).containsKey(userData.getUserNo())){
                CrossTwinsDamageRecordData damageRecordData = initDamageRecord(bossData,userData,beAttackUserData);
                userData.getAttackDamageRecordMap().get(beUserNo).put(userData.getUserNo(),damageRecordData);
            }
            CrossTwinsDamageRecordData damageRecordData = userData.getAttackDamageRecordMap().get(beUserNo).get(userData.getUserNo());
            if(!beAttackUserData.getBeAttackDamageRecordMap().containsKey(beUserNo)){
                beAttackUserData.getBeAttackDamageRecordMap().put(beUserNo,new ConcurrentHashMap<>());
            }
            beAttackUserData.getBeAttackDamageRecordMap()
                    .get(beUserNo)
                    .put(userData.getUserNo(),damageRecordData);
        }
    }

    //同步玩家信息
    public void pvpSyncUserData(long serverId, long userId) {
        TwinsProto.CrossTwinsUserDataMsg.Builder syncBuilderMsg = TwinsProto.CrossTwinsUserDataMsg.newBuilder();
        syncBuilderMsg.setActivityId(getActivityId());
        CrossTwinsUserData userData = getUserData(userId);
        if(userData != null){
            syncBuilderMsg.setPvpTimes(userData.getHp());
            //是否有奖励可以领取
            syncBuilderMsg.setIsPvpReward(!StringUtils.isNullOrEmpty(userData.getReward()));
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_TWINS_CROSS_SYNC_USER_DATA, syncBuilderMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //玩家掉线了不在房间了要校验
    private void checkRoomUser() {
        Map<Long,TwinsProto.CrossTwinsCheckEnterRoomMsg.Builder> serverCheckMsgMap = new ConcurrentHashMap<>();
        for(int bossId : enterBossRoomMap.keySet()){
            List<Long> bugList = enterBossRoomMap.get(bossId);
            synchronized (bugList){
                int i = 66;
                while (bugList.contains(null) && i > 0){
                    logger.error("移除了boss{},中的空值",bossId);
                    bugList.remove(null);
                    i--;
                }
            }
            List<Long> userIdList = new ArrayList<>(enterBossRoomMap.get(bossId));
            for(long userId : userIdList){
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
                if(userBaseInfo == null)continue;
                if(!serverCheckMsgMap.containsKey(userBaseInfo.getServerId())){
                    TwinsProto.CrossTwinsCheckEnterRoomMsg.Builder syncBuilderMsg = TwinsProto.CrossTwinsCheckEnterRoomMsg.newBuilder();
                    syncBuilderMsg.setActivityId(getActivityId());
                    serverCheckMsgMap.put(userBaseInfo.getServerId(),syncBuilderMsg);
                }
                serverCheckMsgMap.get(userBaseInfo.getServerId()).addUserId(userId);
            }
        }
        for(long serverId : serverCheckMsgMap.keySet()){
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_TWINS_CROSS_CHECK_ENTER_ROOM, serverCheckMsgMap.get(serverId));
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }


    //同步玩家声望
    private void syncPopList(){
        List<CrossTwinsUserData> tempList = new ArrayList<>();
        if(needSyncPopList.size() > 0){
            synchronized (needSyncPopList){
                tempList = new ArrayList<>(needSyncPopList);
                needSyncPopList.clear();
            }
        }
        if(tempList.size() > 0){
            Map<Long,TwinsProto.SimpleCrossConditionSyncMsg.Builder> serverSyncMap = new ConcurrentHashMap<>();
            for(CrossTwinsUserData userData : tempList){
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
                if(userBaseInfo == null)continue;
                if(!serverSyncMap.containsKey(userBaseInfo.getServerId())){
                    TwinsProto.SimpleCrossConditionSyncMsg.Builder syncMsg = TwinsProto.SimpleCrossConditionSyncMsg.newBuilder();
                    syncMsg.setActivityId(getActivityId());
                    serverSyncMap.put(userBaseInfo.getServerId(),syncMsg);
                }
                TwinsProto.SimpleCrossConditionMsg.Builder cdMsg = TwinsProto.SimpleCrossConditionMsg.newBuilder();
                cdMsg.setUserId(userData.getUserId());
                cdMsg.setType(eGamePlayerEventType.TwinsUserScoreRank.getValue());
                cdMsg.setValue(userData.getAllScore() + userData.getAttackScore() + "");
                cdMsg.setParam("");
                serverSyncMap.get(userBaseInfo.getServerId()).addSyncData(cdMsg);
            }
            for(long serverId : serverSyncMap.keySet()){
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_TWINS_CROSS_CONDITION_SYNC, serverSyncMap.get(serverId));
                MessageHelper.sendPacket(serverId, 0, pbMsg);
            }
        }
    }

    private void syncDrawRewardList(){
        List<CrossTwinsLuckDrawRecordData> tempList = new ArrayList<>();
        if(needSyncRecordList.size() > 0){
            synchronized (needSyncRecordList){
                tempList = new ArrayList<>(needSyncRecordList);
                needSyncRecordList.clear();
            }
        }
        if(tempList.size() > 0){
            TwinsProto.TwinsLuckDrawRecordSyncMsg.Builder syncMsg = TwinsProto.TwinsLuckDrawRecordSyncMsg.newBuilder();
            for(CrossTwinsLuckDrawRecordData recordData : tempList){
                TwinsProto.TwinsLuckDrawRecordTempMsg.Builder recordMsg = parseTwinsLuckDrawRecordTempMsg(recordData);
                syncMsg.addInfo(recordMsg);
            }
            for(long serverId : getActivity().getServerIdList()){
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_TWINS_CROSS_LUCK_DRAW_RECORD_SYNC, syncMsg);
                MessageHelper.sendPacket(serverId, 0, pbMsg);
            }
        }
    }
}
